import { removeEmptyNameItem } from "./util.js";
import { isArraySchema } from "./array.js";
import { isObjectSchema } from "./object.js";

/**
 * 把json树转换为标准jsonSchema格式
 * @param {String} type
 * @param {Array} array
 * @param {Function} callback
 * @returns {*}
 * @constructor
 */

class Tree2Schema {
  map;
  constructor(type, array, callback) {
    // 遍历每一项回调方法
    this.map = callback || ((item) => item);
    const json = {
      type: type || "object",
      children: removeEmptyNameItem(array || []),
    };

    return this.parse(json);
  }

  /**
   * 解析树形结构的json描述结构
   * @param json
   * @returns {*}
   */
  parse(json) {
    var result = null;

    if (isObjectSchema(json)) {
      result = this.parseObject(json);
    } else if (isArraySchema(json)) {
      result = this.parseArray(json);
    }

    // 删除无用属性
    this.deleteOverAttr(json);

    // 规范字段
    this.normAttr(json);

    return result;
  }
  /**
   * 解析对象
   * @param json
   * @returns {*}
   */
  parseObject(json) {
    json.properties = {};
    json.required = [];
    this.forEach(json.children, (item) => {
      json.properties[item.name] = item;

      if (item.required) {
        json.required.push(item.name);
      }

      this.parse(item);
    });
    delete json.children;
    return json;
  }
  /**
   * 解析数组
   * @param json
   * @returns {*}
   */
  parseArray(json) {
    json.items = {};

    let required = [];
    let properties = null;

    this.forEach(json.children, (item) => {
      if (properties === null) {
        properties = {};
      }
      properties[item.name] = item;

      if (item.required) {
        required.push(item.name);
      }

      this.parse(item);
    });

    if (properties) {
      json.items = {
        type: "object",
        required: required,
        properties: properties,
      };
    }

    delete json.children;
    return json;
  }
  /**
   * 遍历对象/数组
   * @param {Object|Array} obj
   * @param {Function} callback
   */
  forEach(obj, callback) {
    for (let key in obj) {
      callback.call(obj, this.map(obj[key]), key, obj);
    }
  }

  /**
   * 规范jsonSchema属性，如果不是标准属性名，加个@前缀
   * @param json
   */
  normAttr(json) {
    ["alias", "name", "enums"].forEach((name) => {
      if (json[name]) {
        json["@" + name] = json[name];
      }

      delete json[name];
    });
  }

  /**
   * 删除多余属性
   * @param json
   */
  deleteOverAttr(json) {
    deleteOverAttr(json, [
      "type",
      "required",
      "alias",
      "name",
      "enums",
      "properties",
      "default",
      "items",
    ]);

    if (Array.isArray(json.enums)) {
      json.enums = removeEmptyNameItem(json.enums);
      if (json.enums.length) {
        json.enums.forEach((item) =>
          deleteOverAttr(item, ["type", "name", "alias", "value"])
        );
        return;
      }
    }
    delete json.enums;
  }
}

/**
 * 删除无关属性
 * @param {Object} json
 * @param {Array} attrs
 */
const deleteOverAttr = function (json, attrs) {
  for (let key in json) {
    if (!attrs.includes(key)) {
      delete json[key];
    }
  }
};

export default Tree2Schema;
